<!DOCTYPE html>
<html>
<!--
Copyright 2013 The Closure Library Authors. All Rights Reserved.

Use of this source code is governed by the Apache License, Version 2.0.
See the COPYING file for details.
-->
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Closure Unit Tests - goog.async.nextTick</title>
<script src="../base.js"></script>
<script>
goog.require('goog.async.nextTick');
goog.require('goog.debug.ErrorHandler');
goog.require('goog.debug.entryPointRegistry');
goog.require('goog.testing.AsyncTestCase');
goog.require('goog.testing.jsunit');
goog.require('goog.testing.MockClock');
</script>
</head>
<body>
<script>

var asyncTestCase = goog.testing.AsyncTestCase.createAndInstall(
    'asyncNextTickTest');

var clock;

function setUp() {
  clock = null;
}

function tearDown() {
  if (clock) {
    clock.uninstall();
  }
  goog.async.nextTick.setImmediate_ = undefined;
}


function testNextTick() {
  var c = 0;
  var max = 100;
  var async = true;
  var counterStep = function(i) {
    async = false;
    assertEquals('Order correct', i, c);
    c++;
    if (c === max) {
      asyncTestCase.continueTesting();
    }
  };
  for (var i = 0; i < max; i++) {
    goog.async.nextTick(goog.partial(counterStep, i));
  }
  assertTrue(async);
  asyncTestCase.waitForAsync('Wait for callback');
}


function testNextTickContext() {
  var context = {};
  var c = 0;
  var max = 10;
  var async = true;
  var counterStep = function(i) {
    async = false;
    assertEquals('Order correct', i, c);
    assertEquals(context, this);
    c++;
    if (c === max) {
      asyncTestCase.continueTesting();
    }
  };
  for (var i = 0; i < max; i++) {
    goog.async.nextTick(goog.partial(counterStep, i), context);
  }
  assertTrue(async);
  asyncTestCase.waitForAsync('Wait for callback');
}


function testNextTickMockClock() {
  clock = new goog.testing.MockClock(true);
  var result = '';
  goog.async.nextTick(function() {
    result += 'a';
  });
  goog.async.nextTick(function() {
    result += 'b';
  });
  goog.async.nextTick(function() {
    result += 'c';
  });
  assertEquals('', result);
  clock.tick(0);
  assertEquals('abc', result);
}


function testNextTickProtectEntryPoint() {
  var errorHandlerCallbackCalled = false;
  var errorHandler = new goog.debug.ErrorHandler(function() {
    errorHandlerCallbackCalled = true;
  });

  // This is only testing wrapping the callback with the protected entry point,
  // so it's okay to replace this function with a fake.
  goog.async.nextTick.setImmediate_ = function(cb) {
    try {
      cb();
      fail('The callback should have thrown an error.');
    } catch (e) {
      assertTrue(
          e instanceof goog.debug.ErrorHandler.ProtectedFunctionError);
    }
    asyncTestCase.continueTesting();
  };
  var origSetImmediate;
  if (window.setImmediate) {
    origSetImmediate = window.setImmediate;
    window.setImmediate = goog.async.nextTick.setImmediate_;
  }
  goog.debug.entryPointRegistry.monitorAll(errorHandler);

  function thrower() {
    throw Error('This should be caught by the protected function.');
  }
  asyncTestCase.waitForAsync('Wait for callback');
  goog.async.nextTick(thrower);
  window.setImmediate = origSetImmediate;
}

</script>
</body>
</html>
